package org.pupil.rpc.tolerant.FaultTolerantStrategyImpl;

import lombok.extern.slf4j.Slf4j;
import org.pupil.rpc.common.ServiceMeta;
import org.pupil.rpc.tolerant.FaultTolerantStrategy;
import org.pupil.rpc.tolerant.FaultTolerantStrategyShareContainer;
import org.springframework.util.ObjectUtils;

import java.util.Collection;

/**
 * 故障转移
 */
@Slf4j
public class FailoverFaultTolerantStrategy implements FaultTolerantStrategy {
    @Override
    public void handler() {
        // 获取容错策略数据共享容器
        FaultTolerantStrategyShareContainer shareContainer = FaultTolerantStrategyShareContainer.getInstance();
        // 运行次数
        long count = shareContainer.getCount();
        // 剩余当前服务节点（空闲状态）
        Collection<ServiceMeta> otherServiceMeta = shareContainer.getOtherServiceMeta();
        // 错误信息
        String errorMsg = shareContainer.getErrorMsg();
        // 服务名
        String serviceName = shareContainer.getServiceName();

        log.warn("rpc 调用失败, 第{}次重试，异常信息：{}", count, errorMsg);
        // 运行次数 + 1
        shareContainer.setCount(count + 1);
        // 判断剩余服务是否为空
        if (!ObjectUtils.isEmpty(otherServiceMeta)) {
            // 获取下一个服务节点
            final ServiceMeta next = otherServiceMeta.iterator().next();
            // 重新设置当前服务节点
            shareContainer.setCurServiceMeta(next);
            // 把当前节点从剩余服务节点中删除
            otherServiceMeta.remove(next);
            shareContainer.setOtherServiceMeta(otherServiceMeta);
        } else {
            final String msg = String.format("rpc 调用失败, 无服务可用 serviceName：{%s}, 异常信息：{%s}", serviceName, errorMsg);
            log.warn(msg);
            throw new RuntimeException(msg);
        }
    }
}
